package lk.icta.core.entity;

import lk.icta.common.entity.BaseEntity;

import javax.persistence.*;
import java.util.List;

/**
 * @author Kusal Samarakoon
 */
@Entity
@Table(schema = "ELAND_RAIL")
@NamedQueries({
        @NamedQuery(
                name = "getActiveRailwayAlienationByLandId",
                query = "SELECT a FROM AlienationRailway a WHERE a.land.id = :landId"
        ),
        @NamedQuery(
                name = "getAlienationRailwayByStateSetUser",
                query = "SELECT a FROM AlienationRailway a WHERE " +
                        "(1 = :ignoreDS AND a.approveState in (:stateSet)) OR " +
                        "(0 = :ignoreDS AND (a.approveState in (:stateSet) AND  a.land.district IN (:DSList) AND (a.land.branch.id =:branchId) OR (1 =:showMigs AND a.land.branch.id= 4))) OR " +
                        "(2 = :ignoreDS AND a.approveState in (:stateSet) AND (a.land.branch.id =:branchId)) "

        ),
        @NamedQuery(
                name = "getAlienationRailwayByTrackAndDistrict",
                query = "SELECT a.id FROM AlienationRailway a WHERE " +
                        "(1 = :ignoreTrack AND a.land.district.id =:districtId) OR " +
                        "(0 = :ignoreTrack AND a.land.district.id =:districtId AND  a.land.railwayTrack.id =:railwayTrackId)"

        ),
        @NamedQuery(
                name = "getAlienationRailwayByStateSet",
                query = "SELECT a FROM AlienationRailway a WHERE " +
                        "(a.approveState in (:stateSet)) "
        ),
        @NamedQuery(
                name = "getAlienationRailwayByLeaseId",
                query = "SELECT a FROM AlienationRailway a WHERE " +
                        "(1 = :ignoreDS AND a.referenceNo LIKE :leaseId) OR " +
                        "(0 = :ignoreDS AND a.referenceNo LIKE :leaseId AND  a.land.district IN (:DSList) AND (a.land.branch.id =:branchId )) OR " +
                        "(2 = :ignoreDS AND a.referenceNo LIKE :leaseId AND (a.land.branch.id =:branchId )) "

        ),

        @NamedQuery(
                name = "getAlienationRailwayByLeaseIdAndStateSet",
                query = "SELECT a FROM AlienationRailway a WHERE " +
                        "(1 = :ignoreDS AND a.referenceNo LIKE :leaseId AND a.approveState in (:stateSet)) OR " +
                        "(0 = :ignoreDS AND a.referenceNo LIKE :leaseId AND a.approveState in (:stateSet) AND  a.land.district IN (:DSList) AND (a.land.branch.id =:branchId )) OR " +
                        "(2 = :ignoreDS AND a.referenceNo LIKE :leaseId AND a.approveState in (:stateSet) AND (a.land.branch.id =:branchId )) "

        ),
        @NamedQuery(
                name = "getAllAlienationRailwaysCountByState",
                query = "SELECT count(a) FROM AlienationRailway a WHERE " +
                        "(1 = :ignoreDS AND a.approveState in (:stateSet)) OR " +
                        "(0 = :ignoreDS AND (a.approveState in (:stateSet) AND  a.land.district IN (:DSList) AND (a.land.branch.id =:branchId) OR a.land.branch.id= 4)) OR " +
                        "(2 = :ignoreDS AND a.approveState in (:stateSet) AND (a.land.branch.id =:branchId)) "
        ),
        @NamedQuery(
                name = "getAlienationByValuationStartDay",
                query = "SELECT a FROM AlienationRailway a WHERE DAY(a.valuation.lastValuationPeriodStart) =:Day AND MONTH(a.valuation.lastValuationPeriodStart) =:Month"
        ),
        @NamedQuery(
                name = "getAlienationByStartedDay",
                query = "SELECT a FROM AlienationRailway a WHERE DAY(a.leaseDetail.leaseStartingDate)=:Day AND MONTH(a.leaseDetail.leaseStartingDate)=:Month"
        ),
        @NamedQuery(
                name = "getAlienationsByIdRnage",
                query = "SELECT a FROM AlienationRailway a WHERE a.id >=:start AND a.id <=:end"
        ),
        @NamedQuery(
                name = "getAlienationReferenceNoLike",
                query = "SELECT a FROM AlienationRailway a WHERE a.referenceNo LIKE :refNo"
        )
})
public class AlienationRailway extends BaseEntity {

    public enum State {
        ARCHIVED,   // 0 - state. Archived and can not be edited nor available for alienation

        DATA_ENTRY,  // 1 - state. Land is in data entry state  by subject clerk

        APPROVED_BY_BO,   // 2 - state. Land is in approve by Branch Officer
        REJECTED_BY_BO,   // 3 - state. Land is in reject by Branch Officer Not available for alienation

        APPROVED_BY_SH,   // 4 - state. Land is in approve by  Section Head
        REJECTED_BY_SH,   // 5 - state. Land is in reject by Section Head   Not available for alienation

        APPROVED_BY_SDH,   // 6 - state. Land is in approve by  Sub Department Head
        REJECTED_BY_SDH,   // 7 - state. Land is in reject by  Sub Department Head  Not available for alienation

        APPROVED_BY_DH,   // 8 - state. Land is in approve by Department Head
        REJECTED_BY_DH,   // 9 - state. Land is in reject by Department Head  Not available for alienation
    }

    public enum MigrationState {
        NONE("Normal"),         // 0 - Non migrated record
        ACCESS_DB("Access Data"),    // 1 - Migrated form Access DB
        EXCEL("Excel Data");        // 2 - Migrated from Excel Sheets

        private String enLabel;

        MigrationState(String enLanbel) {
            this.enLabel = enLanbel;
        }

        public String getEnLabel() {
            return enLabel;
        }
    }

    /**
     * The parent land that is going to be alienated
     */
    @ManyToOne(cascade = {CascadeType.REFRESH})
    @JoinColumn(nullable = true)
    private LandRailway land;

    /**
     * The person who owns the alienation
     */
    @ManyToOne(cascade = {CascadeType.ALL})
    @JoinColumn(nullable = true)
    private Holder holder;

    @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "leaseDetailId", nullable = true)
    private LeaseDetail leaseDetail;

    @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "valuationId", nullable = true)
    private Valuation valuation;

    @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
    @JoinColumn(nullable = false, name = "alienation_id")
    private List<ArrearsHistoryRecord> arrearsHistoryRecords;

    @OneToOne
    @JoinColumn(name = "leaseUsagePrimaryId", nullable = true)
    private LandUsage leaseUsagePrimary;

    @OneToOne
    @JoinColumn(name = "leaseUsageSecondaryId", nullable = true)
    private LandUsage leaseUsageSecondary;

    /**
     * Reference no of the alienation. (Lease no etc.)
     */
    @Column(nullable = false)
    private String referenceNo;

    @Column(nullable = true, columnDefinition = "text")
    public String alienationComment;

    @Column(nullable = true, columnDefinition = "text")
    private String approvalNote;

    @Column(nullable = false)
    private State approveState;

    @Embedded
    private LifeCycleInfo lifeCycleInfo = new LifeCycleInfo();

    @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
    @JoinColumn(nullable = true, name = "alienation_id")
    private List<Occupier> occupiers;

    @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
    @JoinColumn(nullable = false, name = "alienation_id")
    private List<Payment> payments;

    @Column(nullable = false)
    private MigrationState migrationState;

    public Holder getHolder() {
        return holder;
    }

    public void setHolder(Holder holder) {
        this.holder = holder;
    }


    public String getReferenceNo() {
        return referenceNo;
    }

    public void setReferenceNo(String referenceNo) {
        this.referenceNo = referenceNo;
    }


    public LeaseDetail getLeaseDetail() {
        return leaseDetail;
    }

    public void setLeaseDetail(LeaseDetail leaseDetail) {
        this.leaseDetail = leaseDetail;
    }

    public LifeCycleInfo getLifeCycleInfo() {
        return lifeCycleInfo;
    }

    public void setLifeCycleInfo(LifeCycleInfo lifeCycleInfo) {
        this.lifeCycleInfo = lifeCycleInfo;
    }

    public String getAlienationComment() {
        return alienationComment;
    }

    public void setAlienationComment(String alienationComment) {
        this.alienationComment = alienationComment;
    }

    public String getApprovalNote() {
        return approvalNote;
    }

    public void setApprovalNote(String approvalNote) {
        this.approvalNote = approvalNote;
    }

    public State getApproveState() {
        return approveState;
    }

    public void setApproveState(State approveState) {
        this.approveState = approveState;
    }

    public LandRailway getLand() {
        return land;
    }

    public void setLand(LandRailway land) {
        this.land = land;
    }

    public Valuation getValuation() {
        return valuation;
    }

    public void setValuation(Valuation valuation) {
        this.valuation = valuation;
    }

    public List<Occupier> getOccupiers() {
        return occupiers;
    }

    public void setOccupiers(List<Occupier> occupiers) {
        this.occupiers = occupiers;
    }

    public LandUsage getLeaseUsagePrimary() {
        return leaseUsagePrimary;
    }

    public void setLeaseUsagePrimary(LandUsage leaseUsagePrimary) {
        this.leaseUsagePrimary = leaseUsagePrimary;
    }

    public LandUsage getLeaseUsageSecondary() {
        return leaseUsageSecondary;
    }

    public void setLeaseUsageSecondary(LandUsage leaseUsageSecondary) {
        this.leaseUsageSecondary = leaseUsageSecondary;
    }

    public List<Payment> getPayments() {
        return payments;
    }

    public void setPayments(List<Payment> payments) {
        this.payments = payments;
    }

    public MigrationState getMigrationState() {
        return migrationState;
    }

    public void setMigrationState(MigrationState migrationState) {
        this.migrationState = migrationState;
    }

    public List<ArrearsHistoryRecord> getArrearsHistoryRecords() {
        return arrearsHistoryRecords;
    }

    public void setArrearsHistoryRecords(List<ArrearsHistoryRecord> arrearsHistoryRecords) {
        this.arrearsHistoryRecords = arrearsHistoryRecords;
    }
}